
let PARAMS = getHttpParams();

let storedApiKey = sessionStorage.getItem("console-api-key");
let storedSessionId = sessionStorage.getItem("console-session-id");
let lastParameterValues = JSON.parse(sessionStorage.getItem("console-last-parameter-values")) || {};

function getHttpParams() {
    let vars = {};
    let hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for (let i = 0; i < hashes.length; i++) {
        let hash = hashes[i].split('=');
        let key = decodeURI(hash[0]);
        let value = decodeURI(hash[1]);
        vars[key] = value;
    }
    return vars;
}

function initForm() {

    $("#apiKey").val(storedApiKey);
    $("#session").val(storedSessionId);

    let selected = sessionStorage.getItem("console-selected-target");
    if (selected) {
        $("#target").val(selected);
    }

    let command = getCurrentCommand();
    if (command.noSessionKey) {
        $('#session-field input').prop("disabled", true);
    }

    showError(PARAMS.error, PARAMS.error_description);
    let code = PARAMS.code;
    if (code) {
        $("#code").val(code);
    }

    if (command.filterExample) {
        $("#filter-input").val(JSON.stringify(command.filterExample, null, 2));
    }
}

function initTarget() {
    let target = document.getElementById("target");
    if (!target) {
        return;
    }

    let group = null;
    for (let i = 0; i < COMMANDS.length; i++) {
        let cmd = COMMANDS[i];
        if (typeof(cmd) == "string") {
            group = document.createElement('optgroup');
            group.label = cmd;
            target.appendChild(group);
        } else {
            let opt = document.createElement('option');
            let text = cmd.method;
            if (["GET", "POST", "PUT"].includes(text)) {
                while (text.length < 6) {
                    text += ".";
                }
            }
            text += (cmd.path ? " " + cmd.path : "");
            opt.text = text;
            opt.value = i;
            if (group) {
                group.appendChild(opt);
            } else {
                target.appendChild(opt);
            }
        }
    }
}

function paramValueElement(name, index, add) {
    let paramValueHtml = '<input class="parameter" type="text" name="_' + name + ':' + index + '" value=""> ';
    if (index > 0) {
        paramValueHtml += '<a href="#" class="removeRow" onclick="removeParamRow(\'' + name + '\', this)">Remove</a> ';
    }
    if (add) {
        paramValueHtml += '<span class="addRow">'
        if (index > 0) { paramValueHtml += ' | '; }
        paramValueHtml += '<a href="#" onclick="addParamRow(\''+ name +'\')">Add</a></span>';
    }

    return paramValueHtml;
}

function removeParamRow(name, obj) {
    let elem = $(obj).parent();
    let index = $(".paramValue." + name).index(elem);
    $(".paramName." + name)[index].remove();
    $(".paramValue." + name)[index].remove();
    for (let idx = index; idx < $(".paramValue." + name).length; idx++) {
        let row = $(".paramValue." + name)[idx];
        $(row).find('.parameter').attr("name", '_' + name + ':' + idx);
    }

    return false;
}

function addParamRow(name) {
    let index = $(".paramValue." + name).length;
    let paramNameHtml = '<div class="paramName paramRow ' + name + '"></div>';
    let paramValueHtml = '<div class="paramValue paramRow ' + name + '" >';

    paramValueHtml += paramValueElement(name, index, false);
    paramValueHtml += '</div>';

    $(".paramName." + name).last().after(paramNameHtml);
    $(".paramValue." + name).last().after(paramValueHtml);

    return false;
}

function populateFields() {
    let command = getCurrentCommand();
    let selected = $("#target option:selected").val();
    if (selected) {
        sessionStorage.setItem("console-selected-target", selected);
    }

    if (command.noSessionKey) {
        $('#session-field input').prop("disabled", true);
    } else {
        $('#session-field input').prop("disabled", false);
    }

    $('#parameters-row').hide();

    let help = $("#help");
    if (command.help) {
        let helpStr = getHelpHtml(command);
        if (command.consoleNote) {
            helpStr += "<p>" + command.consoleNote + "</p>";
        }
        help.html(helpStr);
        help.show();
    } else {
        help.hide();
    }

    if (command.inputExample) {
        $("#input").val(JSON.stringify(command.inputExample, null, 2));
        updateFieldHeight($("#input")[0]);
    }

    let paramContainer = $("#parameters");
    paramContainer.empty();

    let paramNameContainer = $("#parameters-heading");
    paramNameContainer.empty();

    let valueKey = getlastParamKey(command);
    let paramValueHtml = "";
    let paramNameHtml = "";
    let extraRowInfo = {};
    if (command.params) {
        for (let name in command.params) {
            paramNameHtml += '<div class="paramName paramRow ' + name + '">' + name + '</div>';
            let value = command.params[name];

            paramValueHtml += '<div class="paramValue paramRow ' + name + '">';
            if (value instanceof Array) {
                extraRowInfo[name] = 0;
                if (valueKey in lastParameterValues) {
                    let lastParams = lastParameterValues[valueKey];
                    for (let index = 1; index < Object.keys(lastParams).length; index++) {
                        let rowId = name + ":" + index;
                        if (!(rowId in lastParams)) {
                            break;
                        }
                        extraRowInfo[name]++;
                    }
                }
                paramValueHtml += paramValueElement(name, 0, true);

            } else if (typeof value === "object") {
                paramValueHtml += '<select class="parameter" name="_' + name + '" id="_' + name + '">';
                for (let key in value) {
                    if (value.hasOwnProperty(key)) {
                        paramValueHtml += "<option value='" + key + "'>" + value[key] + "</option>";
                    }
                }
                paramValueHtml += '</select>';
            } else {
                paramValueHtml += '<input class="parameter" type="text" name="_' + name + '" value="' + value + '">';
            }
            paramValueHtml += '</div>';
        }
        $('#parameters-row').show();
    }

    let hasParams = (command.hasInput || command.params || command.filterExample);
    $("#parameters-text").text(hasParams ? "" : "None");

    paramContainer.html(paramValueHtml);
    paramNameContainer.html(paramNameHtml);

    for (let name in extraRowInfo) {
        for (let index = 0; index < extraRowInfo[name]; index++) {
            addParamRow(name);
        }
    }

    if (valueKey in lastParameterValues) {
        let lastParams = lastParameterValues[valueKey];
        for (let id in lastParams) {
            let value = lastParams[id];
            let paramField = $('.parameter[name="_' + id  + '"]');
            if (paramField.length > 0 || id.indexOf(":") > -1) {
                $('.parameter[name="_' + id  + '"]').val(value);
            } else {
                $('textarea[name="_' + id  + '"]').val(value);
            }
        }
    }
}

function showError(error, error_description) {
    if (error) {
        let div = $("#error");
        div.html("error: <b>" + error + "</b><br>error_description: <b>" + error_description + "</b>");
        div.slideDown();
    }
}

function getCurrentCommand() {
    let selected = $("#target option:selected").val();
    if (selected) {
        return COMMANDS[parseInt(selected)];
    }
    return COMMANDS[1];
}

function escapeHtml(value) {
    if (typeof value === "string") {
        value = value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
    } else if (Array.isArray(value)) {
        for (let i = 0; i < value.length; i++) {
            if (typeof value[i] === "string") {
                value[i] = value[i].replace(/</g, "&lt;").replace(/>/g, "&gt;");
            }
        }
    } else if (typeof value === "object") {
        for (let key in value) {
            if (value.hasOwnProperty(key) && typeof value[key] === "string") {
                value[key] = value[key].replace(/</g, "&lt;").replace(/>/g, "&gt;");
            }
        }
    }
    return value;
}

function formatHelpValue(key, value) {
    let valueData;
    if (NUMERIC_VALUES.includes(key) || NUMERIC_VALUES.includes(value)) {
        valueData = escapeHtml(value);
    } else if (value instanceof Array) {
        valueData = JSON.stringify(value);
    } else if (typeof value === "object") {
        valueData = JSON.stringify(value);
    } else if (isNaN(value)) {
        valueData = (value ? '"' + escapeHtml(value) + '"' : '""');
    } else {
        valueData = value;
    }
    return valueData;
}

function getFilterHelpHtml(command) {
    let filterExample = "";
    if (command.filterHelp && Object.keys(command.filterHelp)) {
        let items = Object.keys(command.inputHelp).length;
        let index = 1;

        $.each(command.filterHelp, function(key, value){
            let valueData = formatHelpValue(key, value);
            filterExample += '<strong>' + key + '</strong>: ' + valueData + (index < items ? ',<br/>' : '<br/>');
            index++;
        });
    }

    if (filterExample){
        filterExample = ' \
        <p> \
            ' + filterExample + ' \
        </p>';
    }

    return filterExample;
}

function getInputHelpHtml(command, input) {
    let inputExample = "";
    let indent = "&nbsp;&nbsp;&nbsp;&nbsp;";
    if (input && Object.keys(input)) {
        let items = Object.keys(input).length;
        let index = 1;
        $.each(input, function(key, value){
            let valueData = formatHelpValue(key, value);
            if (typeof valueData === "string") {
                valueData = valueData.replace('"unitId"', 'unitId');
            }
            if (command.hasInput) {
                inputExample += indent + '<strong>"' + key + '"</strong>: ' + valueData + (index < items ? ',<br/>' : '');
            } else {
                inputExample += '<strong>' + key + '</strong>: ' + valueData + '<br/>';
            }
            index++;
        });

        if (command.method === "POST") {
            inputExample = ' \
                <p> \
                    { <br/> \
                    ' + inputExample + ' <br/> \
                    } \
                </p>';
        } else {
            inputExample = ' \
                <p> \
                    ' + inputExample + ' \
                </p>';
        }
    }
    return inputExample;
}

function getHelpHtml(command) {
    let helpStr = '\
        <p> \
            <strong>' + command.title + '</strong> \
        </p><p> \
            ' + command.help + ' \
        </p>';

    if (command.inputHelp) {
        helpStr += '\
            Required parameters: <br/> \
            <div class="input-example"> \
               ' + getInputHelpHtml(command, command.inputHelp) + ' \
            </div>';
    }

    if (command.filterHelp) {
        helpStr += '\
            Filter options'+ (command.filterOptionsRequired ? " (mandatory)": "") +': <br/> \
            <div class="filter-example"> \
                ' + getFilterHelpHtml(command) + ' \
            </div>';
    }
    return helpStr;
}

function getlastParamKey(command) {
    return command.method + (command.path ? command.path : "");
}

function handleInputValues(command, params, sessionId, apiKeyId) {
    let headers = {};
    if (params) {
        let valueKey = getlastParamKey(command);
        lastParameterValues[valueKey] = params;
        sessionStorage.setItem("console-last-parameter-values", JSON.stringify(lastParameterValues));
    }

    if (sessionId) {
        headers = { "X-Casambi-Session" : sessionId };
        sessionStorage.setItem("console-session-id", sessionId);
    }
    if (apiKeyId)  {
        headers["X-Casambi-Key"] = apiKeyId;
        log("Session " + sessionId);
        log("Api Key " + apiKeyId);
        sessionStorage.setItem("console-api-key", apiKeyId);
    } else if (sessionId) {
        log("Session " + sessionId);
    }
    return headers;
}

function getParams() {
    let params = {};
    let elems = $(".parameter");
    let requiredFieldMissing = false;
    let command = getCurrentCommand();

    elems.each(function (i, e) {
        if (!e.value) {
            requiredFieldMissing = true;
            return;
        }
        let name = e.name.substring(1);
        params[name] = e.value;
    });

    if (requiredFieldMissing) {
        return false;
    }

    if (command.hasInput) {
        params["input"] = $("#input").val();
    }
    if (command.filterExample) {
        params["filter-input"] = $("#filter-input").val();
    }

    return params;
}

function getFilterOptions() {
    let params = {};
    let command = getCurrentCommand();
    let hasFilterData = command.filterExample || false;
    let extraParams = $("#filter-input").val();
    if (hasFilterData && extraParams) {
        let lines = extraParams.split(/[\r\n]/);
        if (extraParams.search("[?&]") >= 0) {
            extraParams = extraParams.replace("?", "");
            lines = extraParams.split("&");
        }

        for (let i = 0; i < lines.length; i++) {
            let line = lines[i].trim();
            if (line) {
                let x = line.indexOf(":");
                if (x == -1) {
                    x = line.indexOf("=");
                }
                if (x > 0) {
                    let name = line.substring(0, x).trim().replace(new RegExp('"', 'g'), '');
                    let value = line.substring(x + 1).trim().replace(new RegExp('"', 'g'), '');
                    value = value.replace(new RegExp(',\s*$', 'g'), ''); // remove last comma..
                    let oldValue = params[name];
                    if (oldValue == undefined) {
                        params[name] = value;
                    } else if (oldValue instanceof Array) {
                        oldValue.push(value);
                    } else {
                        params[name] = [oldValue, value];
                    }
                }
            }
        }
    }

    return params;
}

function getMillis() {
    return new Date().getTime();
}

function parsePath(text, params) {
    for (let name in params) {
        let value = params[name];
        let newtext = text.replace("{" + name + "}", value);
        if (text != newtext) {
            delete params[name];
            text = newtext;
        }
    }
    return text;
}

function pad(i) {
    if (i < 10) {
        return "0" + i;
    } else {
        return i;
    }
}

function log(msg) {
    let date = new Date();
    let time = "[" + pad(date.getHours()) + ":" + pad(date.getMinutes()) + "." + pad(date.getSeconds()) + "]";
    let tag = $("#log");
    let html = tag.html();
    if (html) {
        tag.html(html + "<br>" + time + " " + msg);
    } else {
        tag.html(time + " " + msg);
    }
}

function clearLog() {
    $("#log").html("");
    return false;
}

function clearResult() {
    $("#output").val("");
    updateFieldHeight($("#output")[0]);
    return false;
}

function clearSession() {
    $("#session").val("");
    sessionStorage.setItem("console-session-id", "");
    return false;
}

function clearApiKey() {
    $("#apiKey").val("");
    sessionStorage.setItem("console-api-key", "");
    return false;
}

function updateFieldHeight(element) {
    element.style.height = 0;
    element.style.height = (element.scrollHeight + 5) + "px";
}

